讓我們使用上一篇安裝的 Contentlayer,實作首頁文章列表功能,呈現所有 Markdown 文章。
結果截圖如下:
我的個人網站裡也有此系列的好讀版,程式碼更易讀、也支援深色模式和側邊目錄,歡迎前往閱讀!
上一篇我們在 contentlayer.config.ts
設定了放文章的路徑,Contentlayer 會去讀取 content/posts/**/*.md
,也就是 content/posts/
裡面的所有 .md 檔案,變成 allPosts 陣列給我們。
但 Contentlayer 不保證文章的排序,而我希望首頁文章列表能從新到舊排列,因此我們需要自己排序文章陣列。
我們將使用 date-fns 來根據文章的 date 屬性排序。
pnpm add date-fns
引入 date-fns 的 compareDesc function,來排序 allPosts,並 export 成 allPostsNewToOld 常數,供稍後首頁文章列表使用:
import { allPosts, Post } from 'contentlayer/generated';
import {
defineDocumentType,
defineNestedType,
makeSource,
} from 'contentlayer/source-files';
import { compareDesc } from 'date-fns'; # Add this
export { allPosts, defineDocumentType, defineNestedType, makeSource, Post };
# Add the following
export const allPostsNewToOld =
allPosts?.sort((a, b) => {
return compareDesc(new Date(a.date), new Date(b.date));
}) || [];
修改 /src/pages/index.tsx:
import type { NextPage } from 'next';
import Head from 'next/head';
import Image from 'next/image';
import { allPostsNewToOld, Post } from '@/lib/contentLayerAdapter';
import styles from '@/styles/Home.module.css';
export function getStaticProps() {
const posts = allPostsNewToOld;
return { props: { posts } };
}
type Props = {
posts: Post[];
};
const Home: NextPage<Props> = ({ posts }) => {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>
<p className={styles.description}>
Get started by editing{' '}
<code className={styles.code}>pages/index.tsx</code>
</p>
<div className={styles.grid}>
{posts.map((post) => (
<a key={post.slug} href={post.path} className={styles.card}>
<h2>{post.title}</h2>
<p>{post.description}</p>
</a>
))}
</div>
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
);
};
export default Home;
完成了!使用 pnpm dev
並瀏覽首頁,你應該就會看到首頁顯示出了兩篇文章,截圖如下:
恭喜你成功引入 Contentlayer 處理完的 Markdown 文章,顯示在首頁文章列表!
但如果你點擊這兩篇文章,會看到 404 錯誤畫面,這是因為我們還沒實作文章內頁。
下一篇文章就讓我們來實作文章內頁,顯示完整文章內容!